/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.toolkit.shape.annotation.impl;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import org.apache.log4j.Logger;

import who.tmap.toolkit.impl.ShapeHelper;
import who.tmap.toolkit.shape.impl.BaseMapShapeImpl;

/**
 * A base class for annotation shapes
 * @author stl
 *
 */
public abstract class BaseAnnotationGraphicShapeImpl extends BaseMapShapeImpl {

    private static Logger logger = Logger.getLogger(BaseAnnotationGraphicShapeImpl.class);    
	
	protected Point2D pt;
	protected double width;
	protected double height;	
	protected int fillPattern;	
	protected Color backgroundColor;
	
	protected Shape shape;
	protected ShapeHelper shapeHelper =new ShapeHelper();
	
	BaseAnnotationGraphicShapeImpl() {
		super();
	}

	public Point2D getPt() {
		return pt;
	}

	public void setPt(Point2D pt) {
		this.pt = pt;
	}

	public double getWidth() {
		return width;
	}

	public void setWidth(double width) {
		this.width = width;
	}	
	
	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}		

	public int getFillPattern() {
		return fillPattern;
	}

	public void setFillPattern(int fillPattern) {
		this.fillPattern = fillPattern;
	}		
	
	public Color getBackgroundColor() {
		return backgroundColor;
	}

	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}	

	protected void displaySelectionHandles( Graphics g ) {
		if ( isSelected() ) {	            
			displayHandleRectangle( (Graphics2D)g, bounds.getX(), bounds.getY() );
			displayHandleRectangle( (Graphics2D)g, bounds.getX(), bounds.getY() + bounds.getHeight() );
			
			displayHandleRectangle( (Graphics2D)g, bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight() );
			displayHandleRectangle( (Graphics2D)g, bounds.getX() + bounds.getWidth(), bounds.getY() );
		}
	}	

	public void fill(Graphics g) {
		fill( g, getFillColor() );
	}

	public void fill(Graphics g, Color color) {
		if ( color != null ) {
			Graphics2D g2d =(Graphics2D)g;
			
			Color prevColor =g2d.getColor();
			
			g2d.setColor( color );
			
			g2d.fill( shape );
			
			g2d.setColor( prevColor );
		}

	}

	public boolean contains(Point2D p) {
		return shape != null && p != null ? shape.contains(p) : false;
	}

	public boolean isInside(Rectangle2D r) {
		return r != null && bounds != null ? r.contains( bounds ) : false;
	}

	public int getHandleIndexAt(Point2D p) {
	    int handle =-1;
		
		if ( getHandleRectangle( bounds.getX(), bounds.getY() ).contains( p ) ) {
			handle =0;
		} else if ( getHandleRectangle( bounds.getX(), bounds.getY() + bounds.getHeight() ).contains( p ) ) {
		    handle =1;
		} else if ( getHandleRectangle( bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight() ).contains( p ) ) {
		    handle =2;
		} else if ( getHandleRectangle( bounds.getX() + bounds.getWidth() , bounds.getY() ).contains( p ) ) {
		    handle =3;
		}
			
		return handle;
	}

	public void updateShape(int handlerIdx, Point2D p) {
		double x =0, y =0, w =0, h =0;		
		
		//logger.debug( "handler=" + handlerIdx );
		
	    switch( handlerIdx ) {
			case 0:
				x =p.getX();
				y =p.getY();
				w =bounds.getMaxX() -p.getX();
				h =bounds.getMaxY() - p.getY();
				break;	  	    
	    
	    	case 1:
	    		x =p.getX();
	    		y =pt.getY();	    		
	    		w =bounds.getMaxX() -p.getX();
	    		h =p.getY() - bounds.getMinY();
	    	    break;	    
	    	    
	    	case 2:
	    		x =pt.getX();
	    		y =pt.getY();
	    	    w =p.getX() - bounds.getMinX();
	    	    h =p.getY() - bounds.getMinY();
	    	    break;
	    	    
	    	case 3:
	    		x =pt.getX();
	    		y =p.getY();
	    		w =p.getX() - bounds.getMinX();
	    		h =bounds.getMaxY() - p.getY();	    	    
	    	    break;
	    }
	    
		if ( w > 0 && h > 0 ) {
			getPt().setLocation( x, y );
			setWidth( w );
			setHeight( h );
		}
	    
	    logger.debug( "idx=" + handlerIdx + ", pt=" + getPt() + ", width=" + width + ", height=" + height );

	    // For test purpose only
	    // Some annotations shapes are centered !
	    bounds.setRect( pt.getX(), pt.getY(), w, h );
	}

	public void moveShape(Point2D anchor, Point2D movingAnchor) {
	    double offsetX =movingAnchor.getX() - anchor.getX();
	    double offsetY =movingAnchor.getY() - anchor.getY();
	    
	    pt.setLocation( pt.getX() + offsetX, pt.getY() + offsetY );	
	 
	    // STL 2009.01.06
	    // works with most part of the annotations (the ones that are not centered)
	    bounds.setRect( pt.getX(), pt.getY(), bounds.getWidth(), bounds.getHeight() );
	}

}
